package geradatawarehouse.dao.config;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.naming.ConfigurationException;

import org.apache.log4j.Logger;

public class ConnectionConfiguration {

	public enum DatabaseType {
		ORACLE("oracle", "oracle.jdbc.OracleDriver"), POSTGRES("postgres",
				"org.postgresql.Driver");
		private final String propertiesPrefix;
		private final String driverClass;

		private DatabaseType(String propertiesPrefix, String driverClass) {
			this.propertiesPrefix = propertiesPrefix;
			this.driverClass = driverClass;
		}

		public String buildConnectionString(String serverAddress,
				String portNumber, String dbName) {
			if (this == ORACLE) {
				return "jdbc:oracle:thin:@" + serverAddress + ":" + portNumber
						+ ":" + dbName;
			} else if (this == POSTGRES) {
				return "jdbc:postgresql://" + serverAddress + ":" + portNumber
						+ "/" + dbName + "?charSet=UTF-16";
			}
			return null;
		}

		public String getDriverClass() {
			return this.driverClass;
		}

		public String getPropertiesPrefix() {
			return this.propertiesPrefix;
		}

	}

	private static final String DBCONFIG_PROPERTIES_FILE = "dbconfig.properties";

	private static Map<DatabaseType, ConnectionConfiguration> configMap = new HashMap<DatabaseType, ConnectionConfiguration>();

	private static final Logger LOGGER = Logger
			.getLogger(ConnectionConfiguration.class);

	public static ConnectionConfiguration getInstance(DatabaseType type)
			throws IOException {
		ConnectionConfiguration connectionConfiguration = ConnectionConfiguration.configMap
				.get(type);

		if (connectionConfiguration == null) {
			connectionConfiguration = new ConnectionConfiguration(type);
			ConnectionConfiguration.configMap
					.put(type, connectionConfiguration);
		}

		return connectionConfiguration;
	}

	private final String connDriverClass;
	private final String dbName;
	private final String password;
	private final String portNumber;
	private final String serverAddress;
	private final String username;

	private final DatabaseType databaseType;

	private ConnectionConfiguration(DatabaseType databaseType)
			throws IOException {

		InputStream is = new FileInputStream(
				ConnectionConfiguration.DBCONFIG_PROPERTIES_FILE);

		Properties p = new Properties();

		p.load(is);

		this.databaseType = databaseType;

		this.serverAddress = p.getProperty(this.databaseType
				.getPropertiesPrefix() + "host");
		this.portNumber = p.getProperty(this.databaseType.getPropertiesPrefix()
				+ "port");
		this.dbName = p.getProperty(this.databaseType.getPropertiesPrefix()
				+ "base");
		this.username = p.getProperty(this.databaseType.getPropertiesPrefix()
				+ "user");
		this.password = p.getProperty(this.databaseType.getPropertiesPrefix()
				+ "password");
		this.connDriverClass = this.databaseType.getDriverClass();
	}

	public String getConnDriverClass() {
		return this.connDriverClass;
	}

	public String getConnString() throws ConfigurationException {
		String connString = this.databaseType.buildConnectionString(
				this.serverAddress, this.portNumber, this.dbName);

		if (connString != null) {
			return connString;
		}

		String message = "Configuração de conexão" + this + "inválida!";

		ConnectionConfiguration.LOGGER.error(message);

		throw new ConfigurationException(message);
	}

	public String getDbName() {
		return this.dbName;
	}

	public String getPassword() {
		return this.password;
	}

	public String getPortNumber() {
		return this.portNumber;
	}

	public String getServerAddress() {
		return this.serverAddress;
	}

	public String getUsername() {
		return this.username;
	}

}
